﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using static LightCAD.Three.UniformsUtils;
using LightCAD.MathLib;
namespace LightCAD.Three
{
    public static partial class ShaderLib
    {
        public class ShaderObj
        {
            public Uniforms uniforms;
            public string vertexShader;
            public string fragmentShader;
        }
        public static ShaderObj basic = new ShaderObj
        {
            uniforms = mergeUniforms(
               UniformsLib.common,
               UniformsLib.specularmap,
               UniformsLib.envmap,
               UniformsLib.aomap,
               UniformsLib.lightmap,
               UniformsLib.fog),
            vertexShader = ShaderChunk.meshbasic_vert,
            fragmentShader = ShaderChunk.meshbasic_frag
        };
        public static ShaderObj lambert = new ShaderObj()
        {
            uniforms = mergeUniforms(
               UniformsLib.common,
               UniformsLib.specularmap,
               UniformsLib.envmap,
               UniformsLib.aomap,
               UniformsLib.lightmap,
               UniformsLib.emissivemap,
               UniformsLib.bumpmap,
               UniformsLib.normalmap,
               UniformsLib.displacementmap,
               UniformsLib.fog,
               UniformsLib.lights,
        new Uniforms
        {
                { "emissive",new Uniform { value=new Color(0x000000) }}
        }),
            vertexShader = ShaderChunk.meshlambert_vert,
            fragmentShader = ShaderChunk.meshlambert_frag
        };
        public static ShaderObj phong = new ShaderObj
        {
            uniforms = mergeUniforms(
               UniformsLib.common,
               UniformsLib.specularmap,
               UniformsLib.envmap,
               UniformsLib.aomap,
               UniformsLib.lightmap,
               UniformsLib.emissivemap,
               UniformsLib.bumpmap,
               UniformsLib.normalmap,
               UniformsLib.displacementmap,
               UniformsLib.fog,
               UniformsLib.lights,
               new Uniforms    {
                       { "emissive",new Uniform { value=  new Color( 0x000000 ) } },
                       { "specular", new Uniform{ value=  new Color( 0x111111 ) } },
                       {"shininess", new Uniform{ value= 30 }}}),
            vertexShader = ShaderChunk.meshphong_vert,
            fragmentShader = ShaderChunk.meshphong_frag
        };
        public static ShaderObj standard = new ShaderObj
        {
            uniforms = mergeUniforms(
               UniformsLib.common,
               UniformsLib.envmap,
               UniformsLib.aomap,
               UniformsLib.lightmap,
               UniformsLib.emissivemap,
               UniformsLib.bumpmap,
               UniformsLib.normalmap,
               UniformsLib.displacementmap,
               UniformsLib.roughnessmap,
               UniformsLib.metalnessmap,
               UniformsLib.fog,
               UniformsLib.lights,
               new Uniforms {
                       {"emissive" ,new Uniform { value=new Color( 0x000000 ) } },
                       {"roughness",new Uniform { value= 1.0 }},
                       {"metalness",new Uniform { value= 0.0 }},
                       {"envMapIntensity", new Uniform{ value= 1 }} // temporary
               }),
            vertexShader = ShaderChunk.meshphysical_vert,
            fragmentShader = ShaderChunk.meshphysical_frag
        };
        public static ShaderObj toon = new ShaderObj
        {
            uniforms = mergeUniforms(
            UniformsLib.common,
            UniformsLib.aomap,
            UniformsLib.lightmap,
            UniformsLib.emissivemap,
            UniformsLib.bumpmap,
            UniformsLib.normalmap,
            UniformsLib.displacementmap,
            UniformsLib.gradientmap,
            UniformsLib.fog,
            UniformsLib.lights,
            new Uniforms
            {
                    {   "emissive",new  Uniform{ value=new Color(0x000000) }}
            }
            ),
            vertexShader = ShaderChunk.meshtoon_vert,
            fragmentShader = ShaderChunk.meshtoon_frag
        };
        public static ShaderObj matcap = new ShaderObj
        {

            uniforms = mergeUniforms(
        UniformsLib.common,
        UniformsLib.bumpmap,
        UniformsLib.normalmap,
        UniformsLib.displacementmap,
        UniformsLib.fog,
        new Uniforms
        {
                { "matcap", new Uniform{ value= null } }
        }),

            vertexShader = ShaderChunk.meshmatcap_vert,
            fragmentShader = ShaderChunk.meshmatcap_frag
        };
        public static ShaderObj points = new ShaderObj
        {

            uniforms = mergeUniforms(
                UniformsLib.points,
                UniformsLib.fog),
            vertexShader = ShaderChunk.points_vert,
            fragmentShader = ShaderChunk.points_frag
        };
        public static ShaderObj dashed = new ShaderObj
        {
            uniforms = mergeUniforms(
                UniformsLib.common,
                UniformsLib.fog,
                new Uniforms{
                        { "scale",new Uniform { value= 1 } },
                        {"dashSize",new Uniform { value= 1 } },
                        {"totalSize", new Uniform{ value= 2 }}
                }),
            vertexShader = ShaderChunk.linedashed_vert,
            fragmentShader = ShaderChunk.linedashed_frag
        };
        public static ShaderObj depth = new ShaderObj
        {

            uniforms =/*@__PURE__*/ mergeUniforms(
        UniformsLib.common,
        UniformsLib.displacementmap
     ),

            vertexShader = ShaderChunk.depth_vert,
            fragmentShader = ShaderChunk.depth_frag
        };
        public static ShaderObj normal = new ShaderObj
        {
            uniforms = mergeUniforms(
                UniformsLib.common,
                UniformsLib.bumpmap,
                UniformsLib.normalmap,
                UniformsLib.displacementmap,
                new Uniforms
                {
                        { "opacity",new Uniform { value=1.0 } }
                }
             ),
            vertexShader = ShaderChunk.meshnormal_vert,
            fragmentShader = ShaderChunk.meshnormal_frag
        };
        public static ShaderObj sprite = new ShaderObj
        {
            uniforms = mergeUniforms(
                UniformsLib.sprite,
                UniformsLib.fog
             ),
            vertexShader = ShaderChunk.sprite_vert,
            fragmentShader = ShaderChunk.sprite_frag
        };
        public static ShaderObj background = new ShaderObj
        {
            uniforms = new Uniforms {
                    { "uvTransform",new Uniform  { value= new Matrix3() }},
                    { "t2D", new Uniform{ value= null } },
                    {"backgroundIntensity",new Uniform { value= 1 }}
                    },
            vertexShader = ShaderChunk.background_vert,
            fragmentShader = ShaderChunk.background_frag
        };
        public static ShaderObj backgroundCube = new ShaderObj
        {
            uniforms = new Uniforms {
                    {"envMap", new Uniform { value= null } },
                    {"flipEnvMap", new Uniform { value= - 1 }},
                    {"backgroundBlurriness", new Uniform { value= 0 }},
                    { "backgroundIntensity", new Uniform { value= 1 }}
                },
            vertexShader = ShaderChunk.backgroundCube_vert,
            fragmentShader = ShaderChunk.backgroundCube_frag
        };
        public static ShaderObj cube = new ShaderObj
        {
            uniforms = new Uniforms
                {
                    {"tCube", new Uniform { value= null } },
                    {"tFlip", new Uniform { value= -1 }},
                    {"opacity", new Uniform { value= 1.0 }}
                },
            vertexShader = ShaderChunk.cube_vert,
            fragmentShader = ShaderChunk.cube_frag
        };
        public static ShaderObj equirect = new ShaderObj
        {
            uniforms = new Uniforms
                {
                    { "tEquirect", new Uniform { value= null }}
                },
            vertexShader = ShaderChunk.equirect_vert,
            fragmentShader = ShaderChunk.equirect_frag
        };
        public static ShaderObj distanceRGBA = new ShaderObj
        {

            uniforms = mergeUniforms(
        UniformsLib.common,
        UniformsLib.displacementmap,
        new Uniforms{
                { "referencePosition",new Uniform { value= new Vector3() } },
                {"nearDistance",new Uniform { value= 1 }},
                {"farDistance", new Uniform{ value= 1000 }}
        }
     ),
            vertexShader = ShaderChunk.distanceRGBA_vert,
            fragmentShader = ShaderChunk.distanceRGBA_frag
        };
        public static ShaderObj shadow = new ShaderObj
        {
            uniforms = mergeUniforms(
                UniformsLib.lights,
                UniformsLib.fog,
                new Uniforms{
                    { "color", new Uniform{ value=new Color(0x00000) } },
                    { "opacity",new Uniform { value= 1.0 }}
                }),
            vertexShader = ShaderChunk.shadow_vert,
            fragmentShader = ShaderChunk.shadow_frag
        };
        public static ShaderObj physical = new ShaderObj
        {
            uniforms = mergeUniforms(
                ShaderLib.standard.uniforms,
                new Uniforms
                {
                        {"clearcoat",new Uniform{ value= 0 }},
                        {"clearcoatMap",new Uniform{ value= null }},
                        {"clearcoatMapTransform",new Uniform{ value= new Matrix3() }},

                        {"clearcoatNormalMap",new Uniform{ value= null }},
                        {"clearcoatNormalMapTransform",new Uniform{ value= new Matrix3() }},
                        {"clearcoatNormalScale",new Uniform{ value= new Vector2( 1, 1 ) }},

                        {"clearcoatRoughness",new Uniform{ value= 0 }},
                        {"clearcoatRoughnessMap",new Uniform{ value= null }},
                        {"clearcoatRoughnessMapTransform",new Uniform{ value= new Matrix3() }},

                        {"iridescence",new Uniform{ value= 0 }},
                        {"iridescenceMap",new Uniform{ value= null }},
                        {"iridescenceMapTransform",new Uniform{ value= new Matrix3() }},
                        {"iridescenceIOR",new Uniform{ value= 1.3 }},
                        {"iridescenceThicknessMinimum",new Uniform{ value= 100 }},
                        {"iridescenceThicknessMaximum",new Uniform{ value= 400 }},
                        {"iridescenceThicknessMap",new Uniform{ value= null }},
                        {"iridescenceThicknessMapTransform",new Uniform{ value= new Matrix3() }},

                        {"sheen",new Uniform{ value= 0 }},
                        {"sheenColor",new Uniform{ value= /*@__PURE__*/ new Color(0x000000) }},
                        {"sheenColorMap",new Uniform{ value= null }},
                        {"sheenColorMapTransform",new Uniform{ value= new Matrix3() }},
                        {"sheenRoughness",new Uniform{ value= 1 }},
                        {"sheenRoughnessMap",new Uniform{ value= null }},
                        {"sheenRoughnessMapTransform",new Uniform{ value= new Matrix3() }},

                        {"transmission",new Uniform{ value= 0 }},
                        {"transmissionMap",new Uniform{ value= null }},
                         {"transmissionMapTransform",new Uniform{ value= new Matrix3() }},
                        {"transmissionSamplerSize",new Uniform{ value= /*@__PURE__*/ new Vector2() }},
                        {"transmissionSamplerMap",new Uniform{ value= null }},

                        {"thickness",new Uniform{ value= 0 }},
                        {"thicknessMap",new Uniform{ value= null }},
                        {"thicknessMapTransform",new Uniform{ value= new Matrix3() }},

                        {"attenuationDistance",new Uniform{ value= 0 }},
                        {"attenuationColor",new Uniform{ value=  new Color(0x000000) }},

                        {"specularColor",new Uniform{ value=  new Color( 1, 1, 1 ) }},
                        {"specularColorMap",new Uniform{ value=  null}},
                        {"specularColorMapTransform",new Uniform{ value=   new Matrix3()}},
                        {"specularIntensity",new Uniform{ value= 1 }},
                        {"specularIntensityMap",new Uniform{ value= null }},
                        {"specularIntensityMapTransform",new Uniform{ value= new Matrix3()  }}
                }),
            vertexShader = ShaderChunk.meshphysical_vert,
            fragmentShader = ShaderChunk.meshphysical_frag
        };

        public static ShaderObj GetShaderObj(string type)
        {
            switch (type)
            {
                case "depth":
                    return depth;
                case "distanceRGBA":
                    return distanceRGBA;
                case "normal":
                    return normal;
                case "basic":
                    return basic;
                case "lambert":
                    return lambert;
                case "phong":
                    return phong;
                case "toon":
                    return toon;
                case "physical":
                    return physical;
                case "matcap":
                    return matcap;
                case "dashed":
                    return dashed;
                case "points":
                    return points;
                case "shadow":
                    return shadow;
                case "sprite":
                    return sprite;
            }
            return null;
        }
    }
}
